<script setup lang="ts" name="systemDic">
import { onMounted, ref, computed, unref, watch } from 'vue'
import { ElMessage } from 'element-plus'
import { useBaseApi } from '@/api/base'
import type { IFListColumnType, IFListType, DicType } from '@/types/custom'
import {
  Bottom,
  Close,
  CopyDocument,
  Delete,
  DocumentCopy,
  Edit,
  Plus,
  Refresh,
  Search,
  Top
} from '@element-plus/icons-vue'
import { Session } from '@/utils/storage'
import { debounce, isArray, uniq } from 'xe-utils'
import { copyTextToClipboard, pasteText } from '@/utils'

const { GetIFList, GetIFQuery, GetTypeDictionary, SaveTypeDictionary } = useBaseApi()

// 定义变量内容
const loading = ref(false)
const keywords = ref('')
const checked = ref(Session.get('dic_checked') || '')
const checkedColumn = ref('')
const list = ref<IFListType[]>([])
const columns = computed(() => {
  const listItem = list.value.find((f) => f.type_name === checked.value)
  return listItem ? listItem.column : []
})

const checkedType = ref(Session.get('dic_checked_type') || 0)
const options = [
  { label: '表格', value: 0 },
  { label: '查询栏', value: 1 }
]

const loopColumns = computed(() => {
  const search = (keywords.value || '').toLowerCase().trim()
  if (search) {
    return columns.value.filter(
      (f) =>
        f.name.toLowerCase().indexOf(search) !== -1 ||
        f.data_type.toLowerCase().indexOf(search) !== -1
    )
  } else {
    return columns.value
  }
})

const gridData = ref<DicType[]>([])
const loopData = ref<DicType[]>([])

watch(
  () => checkedColumn.value,
  () => {
    setLoopData()
  }
)

/**
 * 设置数据
 */
const setLoopData = () => {
  if (checkedColumn.value) {
    loopData.value = gridData.value.filter((f) => f.column_name === checkedColumn.value)
  } else {
    loopData.value = gridData.value
  }
}

/**
 * 交换位置
 * @param arr
 * @param index1
 * @param index2
 */
function swapArrayElements(arr: DicType[], index1: number, index2: number) {
  arr[index1] = arr.splice(index2, 1, arr[index1])[0]
  return arr
}

/**
 * 删除
 * @param item
 */
const onRemove = (item: DicType) => {
  const index = gridData.value.findIndex(
    (f) =>
      f.column_name === item.column_name &&
      f.type_name === item.type_name &&
      f.value_text === item.value_text
  )
  gridData.value.splice(index, 1)
  setLoopData()
}

/**
 * 排序
 * @param diff
 * @param index
 */
const onSplice = (diff: number, index: number) => {
  swapArrayElements(loopData.value, index, index + diff)
  if (checkedColumn.value) {
    loopData.value.forEach((v, vx) => {
      v.sort = vx
    })
  } else {
    const rows = unref(gridData)
    const keys = uniq(rows.map((v) => v.column_name))
    keys.forEach((column_name) => {
      const ls = rows.filter((f) => f.column_name === column_name)
      ls.forEach((v, vx) => {
        v.sort = vx
      })
    })
  }
}

/**
 * 获取字段个数
 * @param item
 */
const getLength = (item: IFListColumnType) => {
  return gridData.value.filter((f) => f.column_name === item.name).length
}

/**
 * 新增
 */
const onPlus = () => {
  if (checkedColumn.value) {
    const column_list = gridData.value.filter((f) => f.column_name === checkedColumn.value)
    gridData.value.push({
      column_name: checkedColumn.value,
      value_text: '',
      display_text: '',
      sort: column_list?.length || 0
    })
    setLoopData()
  } else {
    ElMessage.warning('请选择字段')
  }
}

/**
 * 选择
 */
const onSelect = () => {
  checkedColumn.value = ''
  Session.set('dic_checked', checked.value)
  Session.set('dic_checked_type', checkedType.value)
  onFetch()
}

/**
 * 选中
 * @param item
 */
const onChecked = (item: IFListColumnType) => {
  if (checkedColumn.value === item.name) {
    checkedColumn.value = ''
  } else {
    checkedColumn.value = item.name
  }
}

/**
 * 查询可选字段
 */
const onFetchIFList = () => {
  if (checkedType.value === 0) {
    GetIFList().then(({ data }) => {
      list.value = data
      if (data.length) {
        if (!data.some((s) => s.type_name === checked.value)) {
          checked.value = data[0].type_name
        }
        onFetch()
      }
    })
  } else if (checkedType.value === 1) {
    GetIFQuery().then(({ data }) => {
      list.value = data
      if (data.length) {
        if (!data.some((s) => s.type_name === checked.value)) {
          checked.value = data[0].type_name
        }
        onFetch()
      }
    })
  }
}

/**
 * 获取所有字典
 */
const onFetch = () => {
  loading.value = true
  GetTypeDictionary({ type_name: checked.value })
    .then(({ data }) => {
      gridData.value = data || []
      setLoopData()
    })
    .finally(() => (loading.value = false))
}

/**
 * 获取所有字典
 */
const onSave = () => {
  loading.value = true
  const rows = unref(gridData)
  SaveTypeDictionary({ type_name: checked.value }, { rows: rows })
    .then(() => {
      ElMessage.success('保存成功')
    })
    .finally(() => (loading.value = false))
}

/**
 * 复制字段数据
 */
const copyColumn = () => {
  const items = unref(loopData)
  if (checkedColumn.value && items.length > 0) {
    copyTextToClipboard(JSON.stringify(items))
  } else {
    ElMessage.warning('没有可复制数据')
  }
}

/**
 * 粘贴字段数据
 */
const pasteColumn = async () => {
  try {
    const result = await pasteText()
    if (result) {
      const json = JSON.parse(result)
      if (isArray(json) && json.length) {
        gridData.value = gridData.value.filter((f) => f.column_name !== checkedColumn.value)
        const list: DicType[] = []
        json.forEach((item, index) => {
          list.push({
            column_name: checkedColumn.value,
            value_text: item.value_text,
            display_text: item.display_text,
            display_type: item.display_type,
            sort: index + 1
          })
        })
        gridData.value.push(...list)
        setLoopData()
      }
    }
  } catch (e) {
    ElMessage.warning('粘贴失败')
  }
}

/**
 * 赋值默认样式
 */
const onInput = debounce((item) => {
  if (item.value_text === '0') {
    item.display_type = 'default'
  } else if (item.value_text === '1') {
    item.display_type = 'primary'
  } else if (item.value_text === '2') {
    item.display_type = 'success'
  } else if (item.value_text === '3') {
    item.display_type = 'warning'
  } else if (item.value_text === '4') {
    item.display_type = 'danger'
  } else if (item.value_text === '5') {
    item.display_type = 'info'
  }
}, 300)

// 页面加载时
onMounted(() => {
  onFetchIFList()
})
</script>
<template>
  <div class="system-dept-container layout-padding">
    <el-row :gutter="10" class="h100">
      <el-col :xs="24" :sm="6" :md="6" :lg="4" :xl="4" class="flex flex-column">
        <el-card shadow="hover" class="h100">
          <div class="h100 flex flex-column">
            <el-select v-model="checkedType" class="mb10 w100" @change="onFetchIFList">
              <el-option
                v-for="(item, index) in options"
                :key="index"
                :value="item.value"
                :label="item.label"
              />
            </el-select>
            <el-select v-model="checked" class="mb10 w100" filterable @change="onSelect">
              <el-option
                v-for="(item, index) in list"
                :key="index"
                :value="item.type_name"
                :label="item.name"
              />
            </el-select>
            <div v-if="!columns.length">
              <el-skeleton />
              <el-skeleton />
              <el-skeleton />
            </div>
            <div class="flex-grow" style="position: relative; min-height: 200px">
              <el-input
                v-model="keywords"
                placeholder="关键字"
                :suffix-icon="Search"
                clearable
                class="mb10"
              />
              <el-scrollbar style="position: absolute">
                <div class="list-group">
                  <div
                    v-for="item in loopColumns"
                    :key="item.name"
                    class="list-group-item flex flex-shrink justify-between"
                    :class="{ active: item.name === checkedColumn }"
                    @click="onChecked(item)"
                  >
                    {{ item.name }}
                    <span v-if="getLength(item)">{{ getLength(item) }}</span>
                  </div>
                </div>
              </el-scrollbar>
            </div>
          </div>
        </el-card>
      </el-col>
      <el-col :xs="24" :sm="18" :md="18" :lg="20" :xl="20" class="h100">
        <el-card shadow="hover" class="h100">
          <div class="flex align-center">
            <el-space :size="5" class="flex align-center flex-grow">
              <el-button type="success" :icon="Plus" @click="onPlus" :loading="loading">
                新增
              </el-button>
              <el-button
                v-if="checkedColumn"
                text
                type="danger"
                @click="checkedColumn = ''"
                :loading="loading"
                :icon="Close"
              >
                {{ checkedColumn }}
              </el-button>
              <el-button
                v-if="checkedColumn"
                type="warning"
                @click="copyColumn"
                :loading="loading"
                :icon="DocumentCopy"
              >
                复制字段数据
              </el-button>
              <el-button
                v-if="checkedColumn"
                type="success"
                @click="pasteColumn"
                :loading="loading"
                :icon="CopyDocument"
              >
                粘贴字段数据
              </el-button>
            </el-space>
            <div class="flex align-center">
              <el-button :icon="Refresh" @click="onFetch" :loading="loading">刷新</el-button>
              <el-button type="primary" :icon="Edit" @click="onSave" :loading="loading">
                保存配置
              </el-button>
            </div>
          </div>
          <el-scrollbar class="flex-grow">
            <div class="pa10">
              <div
                v-for="(item, index) in loopData"
                :key="index"
                class="mb5 flex align-center flex-warp"
              >
                <el-button
                  type="danger"
                  size="small"
                  :icon="Delete"
                  circle
                  @click="onRemove(item)"
                />
                <el-button
                  size="small"
                  :icon="Top"
                  circle
                  :disabled="index <= 0"
                  @click="onSplice(-1, index)"
                />
                <el-button
                  size="small"
                  :icon="Bottom"
                  circle
                  :disabled="index === loopData.length - 1"
                  @click="onSplice(1, index)"
                />
                <el-input
                  v-model="item.value_text"
                  placeholder="值"
                  style="width: 60px"
                  class="ml10"
                  @input="onInput(item)"
                />
                <el-input
                  v-model="item.display_text"
                  placeholder="显示"
                  style="width: 120px"
                  class="ml10"
                />
                <el-select
                  v-model="item.display_type"
                  placeholder="样式"
                  style="width: 100px"
                  class="ml10"
                >
                  <el-option label="默认" value="default" />
                  <el-option label="主题色" value="primary" />
                  <el-option label="绿色" value="success" />
                  <el-option label="黄色" value="warning" />
                  <el-option label="红色" value="danger" />
                  <el-option label="灰色" value="info" />
                </el-select>
                <span class="ml10">{{ item.column_name }}</span>
                <!--                <el-input-number v-model="item.sort" :min="0" :max="10000" class="ml10" />-->
              </div>
            </div>
            <div style="width: 100%; height: 50px"></div>
            <el-empty v-if="!loopData.length" :image-size="100" />
          </el-scrollbar>
        </el-card>
      </el-col>
    </el-row>
  </div>
</template>

<style scoped lang="scss">
.list-group {
  list-style: none;

  .list-group-item {
    position: relative;
    padding: 7px 5px;
    border: 1px solid var(--el-border-color);
    user-select: none;
    cursor: pointer;
    margin-bottom: 5px;

    &.active {
      color: var(--el-color-primary);
      border: 1px solid var(--el-color-primary);
    }
  }

  .list-group-item:first-child {
    border-top-left-radius: 4px;
    border-top-right-radius: 4px;
  }
}
</style>
